package com.rickpan.service;

import com.rickpan.entity.FileInfo;
import com.rickpan.exception.BusinessException;
import com.rickpan.storage.StorageService;
import com.rickpan.storage.url.MinIOUrlGenerationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 文件 URL 管理服务
 * 提供安全的文件访问 URL 生成和管理功能
 */
@Service
public class FileUrlService {
    
    private static final Logger logger = LoggerFactory.getLogger(FileUrlService.class);
    
    @Autowired
    private StorageService storageService;
    
    @Autowired
    private FileManagementService fileManagementService;
    
    @Autowired(required = false)
    private MinIOUrlGenerationService minIOUrlGenerationService;
    
    /**
     * 生成文件下载 URL（带权限检查）
     * 
     * @param userId 用户ID
     * @param fileId 文件ID
     * @return 下载URL
     */
    public String generateSecureDownloadUrl(Long userId, Long fileId) {
        return generateSecureDownloadUrl(userId, fileId, getDefaultDownloadExpiration());
    }
    
    /**
     * 生成文件下载 URL（带权限检查和自定义有效期）
     * 
     * @param userId 用户ID
     * @param fileId 文件ID
     * @param expiration URL有效期
     * @return 下载URL
     */
    public String generateSecureDownloadUrl(Long userId, Long fileId, Duration expiration) {
        // 验证文件访问权限
        FileInfo fileInfo = validateFileAccess(userId, fileId);
        
        // 生成下载URL
        String url = storageService.generateDownloadUrl(fileInfo.getFilePath(), expiration);
        
        logger.debug("生成安全下载URL: userId={}, fileId={}, fileName={}", 
                    userId, fileId, fileInfo.getOriginalName());
        
        return url;
    }
    
    /**
     * 生成文件预览 URL（带权限检查）
     * 
     * @param userId 用户ID
     * @param fileId 文件ID
     * @return 预览URL
     */
    public String generateSecurePreviewUrl(Long userId, Long fileId) {
        return generateSecurePreviewUrl(userId, fileId, getDefaultPreviewExpiration());
    }
    
    /**
     * 生成文件预览 URL（带权限检查和自定义有效期）
     * 
     * @param userId 用户ID
     * @param fileId 文件ID
     * @param expiration URL有效期
     * @return 预览URL
     */
    public String generateSecurePreviewUrl(Long userId, Long fileId, Duration expiration) {
        // 验证文件访问权限
        FileInfo fileInfo = validateFileAccess(userId, fileId);
        
        // 检查文件是否支持预览
        if (!isSupportedForPreview(fileInfo)) {
            throw new BusinessException("文件类型不支持预览");
        }
        
        // 生成预览URL
        String url = storageService.generatePreviewUrl(fileInfo.getFilePath(), expiration);
        
        logger.debug("生成安全预览URL: userId={}, fileId={}, fileName={}", 
                    userId, fileId, fileInfo.getOriginalName());
        
        return url;
    }
    
    /**
     * 批量生成文件下载 URL（带权限检查）
     * 
     * @param userId 用户ID
     * @param fileIds 文件ID列表
     * @return 文件ID到下载URL的映射
     */
    public Map<Long, String> batchGenerateSecureDownloadUrls(Long userId, List<Long> fileIds) {
        return batchGenerateSecureDownloadUrls(userId, fileIds, getDefaultDownloadExpiration());
    }
    
    /**
     * 批量生成文件下载 URL（带权限检查和自定义有效期）
     * 
     * @param userId 用户ID
     * @param fileIds 文件ID列表
     * @param expiration URL有效期
     * @return 文件ID到下载URL的映射
     */
    public Map<Long, String> batchGenerateSecureDownloadUrls(Long userId, List<Long> fileIds, Duration expiration) {
        logger.debug("批量生成安全下载URL: userId={}, {} 个文件", userId, fileIds.size());
        
        // 批量验证文件访问权限
        Map<Long, FileInfo> fileInfoMap = validateBatchFileAccess(userId, fileIds);
        
        // 提取文件路径
        List<String> filePaths = fileInfoMap.values().stream()
            .map(FileInfo::getFilePath)
            .collect(Collectors.toList());
        
        // 批量生成URL
        Map<String, String> pathToUrlMap = storageService.batchGenerateDownloadUrls(filePaths, expiration);
        
        // 转换为文件ID到URL的映射
        return fileInfoMap.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> pathToUrlMap.get(entry.getValue().getFilePath())
            ));
    }
    
    /**
     * 批量生成文件预览 URL（带权限检查）
     * 
     * @param userId 用户ID
     * @param fileIds 文件ID列表
     * @return 文件ID到预览URL的映射
     */
    public Map<Long, String> batchGenerateSecurePreviewUrls(Long userId, List<Long> fileIds) {
        return batchGenerateSecurePreviewUrls(userId, fileIds, getDefaultPreviewExpiration());
    }
    
    /**
     * 批量生成文件预览 URL（带权限检查和自定义有效期）
     * 
     * @param userId 用户ID
     * @param fileIds 文件ID列表
     * @param expiration URL有效期
     * @return 文件ID到预览URL的映射
     */
    public Map<Long, String> batchGenerateSecurePreviewUrls(Long userId, List<Long> fileIds, Duration expiration) {
        logger.debug("批量生成安全预览URL: userId={}, {} 个文件", userId, fileIds.size());
        
        // 批量验证文件访问权限
        Map<Long, FileInfo> fileInfoMap = validateBatchFileAccess(userId, fileIds);
        
        // 过滤支持预览的文件
        Map<Long, FileInfo> previewableFiles = fileInfoMap.entrySet().stream()
            .filter(entry -> isSupportedForPreview(entry.getValue()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        
        if (previewableFiles.isEmpty()) {
            return Map.of();
        }
        
        // 提取文件路径
        List<String> filePaths = previewableFiles.values().stream()
            .map(FileInfo::getFilePath)
            .collect(Collectors.toList());
        
        // 批量生成URL
        Map<String, String> pathToUrlMap = storageService.batchGeneratePreviewUrls(filePaths, expiration);
        
        // 转换为文件ID到URL的映射
        return previewableFiles.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> pathToUrlMap.get(entry.getValue().getFilePath())
            ));
    }
    
    /**
     * 刷新 URL（如果即将过期）
     * 
     * @param userId 用户ID
     * @param fileId 文件ID
     * @param urlType URL类型（download/preview）
     * @return 刷新后的URL
     */
    public String refreshUrlIfNeeded(Long userId, Long fileId, String urlType) {
        if (minIOUrlGenerationService == null) {
            // 本地存储不需要刷新
            if ("download".equals(urlType)) {
                return generateSecureDownloadUrl(userId, fileId);
            } else {
                return generateSecurePreviewUrl(userId, fileId);
            }
        }
        
        // 验证文件访问权限
        FileInfo fileInfo = validateFileAccess(userId, fileId);
        
        Duration expiration = "download".equals(urlType) ? 
            getDefaultDownloadExpiration() : getDefaultPreviewExpiration();
        
        return minIOUrlGenerationService.refreshUrlIfNeeded(fileInfo.getFilePath(), urlType, expiration);
    }
    
    /**
     * 验证文件访问权限
     * 
     * @param userId 用户ID
     * @param fileId 文件ID
     * @return 文件信息
     */
    private FileInfo validateFileAccess(Long userId, Long fileId) {
        try {
            return fileManagementService.getFileDetail(userId, fileId);
        } catch (Exception e) {
            logger.warn("文件访问权限验证失败: userId={}, fileId={}", userId, fileId, e);
            throw new BusinessException("文件不存在或无访问权限");
        }
    }
    
    /**
     * 批量验证文件访问权限
     * 
     * @param userId 用户ID
     * @param fileIds 文件ID列表
     * @return 文件ID到文件信息的映射
     */
    private Map<Long, FileInfo> validateBatchFileAccess(Long userId, List<Long> fileIds) {
        return fileIds.stream()
            .collect(Collectors.toMap(
                fileId -> fileId,
                fileId -> {
                    try {
                        return fileManagementService.getFileDetail(userId, fileId);
                    } catch (Exception e) {
                        logger.warn("文件访问权限验证失败: userId={}, fileId={}", userId, fileId, e);
                        throw new BusinessException("文件不存在或无访问权限: " + fileId);
                    }
                }
            ));
    }
    
    /**
     * 检查文件是否支持预览
     *
     * @param fileInfo 文件信息
     * @return 是否支持预览
     */
    private boolean isSupportedForPreview(FileInfo fileInfo) {
        if (fileInfo.getIsDirectory()) {
            return false;
        }

        String mimeType = fileInfo.getMimeType();
        if (mimeType == null) {
            return false;
        }

        // 支持的预览类型
        return mimeType.startsWith("image/") ||
               mimeType.startsWith("video/") ||  // 添加视频支持
               mimeType.startsWith("text/") ||
               mimeType.equals("application/pdf") ||
               mimeType.equals("application/json") ||
               mimeType.equals("application/xml");
    }
    
    /**
     * 获取默认下载URL有效期
     */
    private Duration getDefaultDownloadExpiration() {
        if (minIOUrlGenerationService != null) {
            return minIOUrlGenerationService.getDefaultDownloadExpiration();
        }
        return Duration.ofHours(1); // 默认1小时
    }
    
    /**
     * 获取默认预览URL有效期
     */
    private Duration getDefaultPreviewExpiration() {
        if (minIOUrlGenerationService != null) {
            return minIOUrlGenerationService.getDefaultPreviewExpiration();
        }
        return Duration.ofMinutes(30); // 默认30分钟
    }
}
